package com.mhc.suzuki.websocket;

import com.alibaba.fastjson.JSON;
import com.mhc.haval.security.model.User;
import com.mhc.suzuki.bo.MessageBO;
import com.mhc.suzuki.config.GetHttpSessionConfigurator;
import com.mhc.suzuki.encoder.MessageEncoder;
import com.mhc.suzuki.exception.SuzukiCommonException;
import com.mhc.suzuki.util.BeanCopierUtil;
import com.mhc.suzuki.vo.MessageVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@ServerEndpoint(value = "/message",
        configurator = GetHttpSessionConfigurator.class,
        encoders = {MessageEncoder.class})
@Component
public class MessageWebSocket {


    private static int onlineCount = 0;


    /**
     * websocket session与登录用户关联, 用于特定用户消息发送
     */
    private static Map<Session, Long> relation = new ConcurrentHashMap<>(64);





    /**
     * 用户新建连接
     * @param session
     */
    @OnOpen
    public void onOpen (Session session, EndpointConfig endpointConfig){
        try{
            //获取user信息
            HttpSession httpSession = (HttpSession) endpointConfig.getUserProperties().get(HttpSession.class.getName());
            User user = (User)((SecurityContext)httpSession.getAttribute("SPRING_SECURITY_CONTEXT")).getAuthentication().getPrincipal();
            //保存user及webSocket信息
            addOnlineCount(user , session);
        } catch (Exception e){
            log.info(e.getMessage(), e);
        }
    }


    /**
     * 用户断开连接
     * @param session
     */
    @OnClose
    public void onClose (Session session){
        try{
            subOnlineCount(session);
        } catch (Exception e){
            log.info(e.getMessage(), e);
        }
    }

    /**
     * 消息发送方法
     * @param messageBO
     * @throws IOException
    */
    public static synchronized void sendMessage (MessageBO messageBO) throws IOException {
        //循环遍历 查找对应session, 发送消息
        log.info("开始查找需要发送消息的用户");
        String message = null;
        boolean exits = false;
        Set<Map.Entry<Session, Long>> entries = relation.entrySet();
        for(Map.Entry<Session, Long> userEntry : entries){
            Long staffId = userEntry.getValue();//系统中存储的用户信息
            if (staffId.equals(messageBO.getStaffId())){
                if (!exits){
                    MessageVO messageVO = BeanCopierUtil.convert(messageBO, MessageVO.class);
                    message = JSON.toJSONString(messageVO);
                    exits = true;
                }
                log.info("用户" + staffId + "匹配， 发送消息");
                Session session = userEntry.getKey();
                session.getBasicRemote().sendText(message);
            }
        }
    }

    public static synchronized  int getOnlineCount (){
        return MessageWebSocket.onlineCount;
    }


     /** 添加新用户连接
     * @param user
     * @param session
     * @throws Exception*/
    public static synchronized void addOnlineCount (User user, Session session) {
        log.info("有新链接加入! sessionId: " + session.getId() + " userName:" + user.getStaffName());
        relation.put(session, user.getStaffId());
        MessageWebSocket.onlineCount++;
        log.info("当前在线人数为" + getOnlineCount());
    }


     /** 用户断开连接
     * @param session
    */
    public static synchronized void subOnlineCount (Session session) throws SuzukiCommonException {
        try{
            Long staffId = relation.get(session);
            log.info("有链接断开! sessionId: " + session.getId() + " userName:" + staffId);
            session.close();
            relation.remove(session);
            MessageWebSocket.onlineCount--;
            log.info("当前在线人数为" + getOnlineCount());
        } catch (IOException e){
            log.error(e.getMessage(), e);
        }
    }

}
